package com.ggshily.swf.abc;

import java.io.DataInput;
import java.io.IOException;

/**
 * This entry is used to define the characteristics of a run-time object(a class instance) within the AVM2.
 * The corresponding <code>class_info</code> entry is used in order to fully define an ACtionScript 3.0 Class.
 * @author playfish_chg
 *
 */
public class ABCClassInstance implements IABCData
{

	public static final int FLAG_ClassSealed = 0x1;
	public static final int FLAG_ClassFinal = 0x2;
	public static final int FLAG_ClassInterface = 0x4;
	public static final int FLAG_ClassProtectedNs = 0x8;
	
	/**
	 * U30, an index into the <code>multiname</code> array of the constant pool; it provides a name
	 * for the class. The entry specified must be a QName.
	 */
	public int name;
	
	/**
	 * U30, an index into the <code>multiname</code> array of the constant pool; it provides the name of
	 * the base class of this class, if any. A value of zero indeicates that this class has no base class.
	 */
	public int superName;
	
	/**
	 * U8, this field is used to identify various options when interpreting the <code>instance_info</code> entry.
	 * It is bit vector; the above entries are defined. Other bits must be zero.
	 */
	public short flags;
	
	/**
	 * U30, this field is present only if the <code>CONSTANT_ProtectedNs</code> bit of <code>flags</code> is set.
	 * It is an index into the <code>namespace</code> array of the constant pool and identifies the namespace that serves
	 * as the protected namespace for this class.
	 */
	public int protectedNs;
	
	/**
	 * U30, this field is the number of entries in the <code>interface</code> array.
	 */
	public int intrfCount;
	
	/**
	 * U30 interface[intrf_count], this array contains indices into the <code>multiname</code> array of the constant pool;
	 * the referenced names specify the interfaces implemented by this class. None of the indices may be zero.
	 */
	public int[] interfaces;
	
	/**
	 * U30, this is an index into the <code>method</code> array of the <code>abcFile</code>; it references the method that
	 * is invoked whenever an object of this class is constructed. This method is sometimes referred to as an instance initializer.
	 */
	public int iinit;
	
	/**
	 * U30, is the number of elements in the <code>trait</code> array.
	 */
	public int traitCount;
	
	/**
	 * trait_info[trait_count], this array defines the set of traits of a class instance.
	 */
	public ABCTraitInfo[] traits;
	
	private ABCFile file;
	
	public ABCClassInstance()
	{
		super();
	}

	public ABCClassInstance(DataInput di) throws IOException
	{
		parseInput(di);
	}

	@Override
	public void parseInput(DataInput di) throws IOException
	{
		name = ABCUtil.readU30(di);
		superName = ABCUtil.readU30(di);
		flags = ABCUtil.readU8(di);
		
		if((flags & FLAG_ClassProtectedNs) > 0)
		{
			protectedNs = ABCUtil.readU30(di);
		}
		
		intrfCount = ABCUtil.readU30(di);
		interfaces = new int[intrfCount];
		for(int i = 0; i < intrfCount; i++)
		{
			interfaces[i] = ABCUtil.readU30(di);
			if(interfaces[i] == 0)
			{
				System.err.println("Wrong interface !!!");
			}
		}
		
		iinit = ABCUtil.readU30(di);
		
		traitCount = ABCUtil.readU30(di);
		traits = new ABCTraitInfo[traitCount];
		for(int i = 0; i < traitCount; i++)
		{
			traits[i] = new ABCTraitInfo(di, file);
		}
	}

	@Override
	public void parseInput(DataInput di, ABCFile file) throws IOException
	{
		this.file = file;
		
		parseInput(di);
	}

}
